Merge "Introduce DatabaseLogEntry::newFromId"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 6 Mar 2018 02:53:18 +0000 (02:53 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 6 Mar 2018 02:53:18 +0000 (02:53 +0000)
includes/deferred/SiteStatsUpdate.php
includes/libs/rdbms/database/DatabaseMysqli.php
tests/phpunit/includes/deferred/SiteStatsUpdateTest.php [new file with mode: 0644]

index 79aab7d..7cb2950 100644 (file)
@@ -66,6 +66,12 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
        public static function factory( array $deltas ) {
                $update = new self( 0, 0, 0 );
 
+               foreach ( $deltas as $name => $unused ) {
+                       if ( !in_array( $name, self::$counters ) ) { // T187585
+                               throw new UnexpectedValueException( __METHOD__ . ": no field called '$name'" );
+                       }
+               }
+
                foreach ( self::$counters as $field ) {
                        if ( isset( $deltas[$field] ) && $deltas[$field] ) {
                                $update->$field = $deltas[$field];
index 9152d1e..984e1c0 100644 (file)
@@ -25,6 +25,7 @@ namespace Wikimedia\Rdbms;
 use mysqli;
 use mysqli_result;
 use IP;
+use stdClass;
 
 /**
  * Database abstraction object for PHP extension mysqli.
@@ -34,8 +35,6 @@ use IP;
  * @see Database
  */
 class DatabaseMysqli extends DatabaseMysqlBase {
-       /** @var mysqli $mConn */
-
        /**
         * @param string $sql
         * @return resource
@@ -162,7 +161,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
         * @return int
         */
        function lastErrno() {
-               if ( $this->conn ) {
+               if ( $this->conn instanceof mysqli ) {
                        return $this->conn->errno;
                } else {
                        return mysqli_connect_errno();
@@ -202,7 +201,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
 
        /**
         * @param mysqli_result $res
-        * @return bool
+        * @return stdClass|bool
         */
        protected function mysqlFetchObject( $res ) {
                $object = $res->fetch_object();
@@ -235,7 +234,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        /**
-        * @param mysqli $res
+        * @param mysqli_result $res
         * @return mixed
         */
        protected function mysqlNumFields( $res ) {
@@ -243,7 +242,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        /**
-        * @param mysqli $res
+        * @param mysqli_result $res
         * @param int $n
         * @return mixed
         */
@@ -266,7 +265,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        /**
-        * @param mysqli $res
+        * @param mysqli_result $res
         * @param int $n
         * @return mixed
         */
@@ -277,7 +276,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        /**
-        * @param mysqli $res
+        * @param mysqli_result $res
         * @param int $n
         * @return mixed
         */
diff --git a/tests/phpunit/includes/deferred/SiteStatsUpdateTest.php b/tests/phpunit/includes/deferred/SiteStatsUpdateTest.php
new file mode 100644 (file)
index 0000000..83e9a47
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @group Database
+ */
+class SiteStatsUpdateTest extends MediaWikiTestCase {
+       /**
+        * @covers SiteStatsUpdate::factory
+        * @covers SiteStatsUpdate::merge
+        */
+       public function testFactoryAndMerge() {
+               $update1 = SiteStatsUpdate::factory( [ 'pages' => 1, 'users' => 2 ] );
+               $update2 = SiteStatsUpdate::factory( [ 'users' => 1, 'images' => 1 ] );
+
+               $update1->merge( $update2 );
+               $wrapped = TestingAccessWrapper::newFromObject( $update1 );
+
+               $this->assertEquals( 1, $wrapped->pages );
+               $this->assertEquals( 3, $wrapped->users );
+               $this->assertEquals( 1, $wrapped->images );
+               $this->assertEquals( 0, $wrapped->edits );
+               $this->assertEquals( 0, $wrapped->articles );
+       }
+
+       /**
+        * @covers SiteStatsUpdate::doUpdate()
+        * @covers SiteStatsInit::refresh()
+        */
+       public function testDoUpdate() {
+               $this->setMwGlobals( 'wgSiteStatsAsyncFactor', false );
+               $this->setMwGlobals( 'wgCommandLineMode', false ); // disable opportunistic updates
+
+               $dbw = wfGetDB( DB_MASTER );
+               $statsInit = new SiteStatsInit( $dbw );
+               $statsInit->refresh();
+
+               $ei = SiteStats::edits(); // trigger load
+               $pi = SiteStats::pages();
+               $ui = SiteStats::users();
+               $fi = SiteStats::images();
+               $ai = SiteStats::articles();
+
+               $dbw->begin( __METHOD__ ); // block opportunistic updates
+
+               $update = SiteStatsUpdate::factory( [ 'pages' => 2, 'images' => 1, 'edits' => 2 ] );
+               $this->assertEquals( 0, DeferredUpdates::pendingUpdatesCount() );
+               $update->doUpdate();
+               $this->assertEquals( 1, DeferredUpdates::pendingUpdatesCount() );
+
+               // Still the same
+               SiteStats::unload();
+               $this->assertEquals( $pi, SiteStats::pages(), 'page count' );
+               $this->assertEquals( $ei, SiteStats::edits(), 'edit count' );
+               $this->assertEquals( $ui, SiteStats::users(), 'user count' );
+               $this->assertEquals( $fi, SiteStats::images(), 'file count' );
+               $this->assertEquals( $ai, SiteStats::articles(), 'article count' );
+               $this->assertEquals( 1, DeferredUpdates::pendingUpdatesCount() );
+
+               $dbw->commit( __METHOD__ );
+
+               $this->assertEquals( 1, DeferredUpdates::pendingUpdatesCount() );
+               DeferredUpdates::doUpdates();
+               $this->assertEquals( 0, DeferredUpdates::pendingUpdatesCount() );
+
+               SiteStats::unload();
+               $this->assertEquals( $pi + 2, SiteStats::pages(), 'page count' );
+               $this->assertEquals( $ei + 2, SiteStats::edits(), 'edit count' );
+               $this->assertEquals( $ui, SiteStats::users(), 'user count' );
+               $this->assertEquals( $fi + 1, SiteStats::images(), 'file count' );
+               $this->assertEquals( $ai, SiteStats::articles(), 'article count' );
+
+               $statsInit = new SiteStatsInit();
+               $statsInit->refresh();
+       }
+}